package com.cuiweiyou.adbctoller.shell;

import com.cuiweiyou.adbctoller.Constant;
import com.cuiweiyou.adbctoller.bean.DeviceModel;
import com.cuiweiyou.adbctoller.bean.WechatNumberModel;
import com.cuiweiyou.adbctoller.util.DateUtil;
import com.cuiweiyou.adbctoller.util.FileUtil;
import com.cuiweiyou.adbctoller.util.LineSeparatorUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * www.gaohaiyan.com
 */
public class AdbExec {

    /**
     * 加载好友名单
     *
     * @param filePath
     * @return
     */
    public List<WechatNumberModel> getWechatNumberList(String filePath) {
        return FileUtil.getWechatNumberList(filePath);
    }

    /**
     * 安装测试app
     *
     * @param list
     */
    public void installTestApp(final List<DeviceModel> list, final String app_debug_androidTest_Path, final String app_debug_Path, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(list)//
                .observeOn(Schedulers.newThread())//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " push " + app_debug_Path + " /data/local/tmp/com.cuiweiyou.uiautomator20";

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("push安装测试宿主app，SQL：", cmd));

                        String result = new ShellExecuter().execCustomShell(cmd, "InstallTestDebugApp", 12);

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("push测试宿主app反馈：", result));
                        return Observable.just(device);
                    }
                })//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " push " + app_debug_androidTest_Path + " /data/local/tmp/com.cuiweiyou.uiautomator20.test";

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("push安装测试器test app，SQL：", cmd));

                        String result = new ShellExecuter().execCustomShell(cmd, "InstallTestTestApp", 13);
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("push测试test app反馈：", result));
                        return Observable.just(device);
                    }
                })//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " -d shell pm install -t -r '/data/local/tmp/com.cuiweiyou.uiautomator20' ; pm install -t -r '/data/local/tmp/com.cuiweiyou.uiautomator20.test'" + System.getProperty("line.separator");

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("install安装测试程序，SQL：", cmd));

                        String result = new ShellExecuter().execCustomShell(cmd, "InstallDebugAndTestShell", 14);
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("install测试程序反馈：", result));
                        return Observable.just(device);
                    }
                })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<DeviceModel>>() {
                               @Override
                               public void accept(List<DeviceModel> list) {
                                   String s = list.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装 test自控app 完毕：", s));
                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.finish("安装 test自控app 完毕", LineSeparatorUtil.transformDeviceToListLog("安装测试器", list));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) {
                                String message = throwable.getMessage();
                                System.out.println("安装 test自控app失败：" + message);
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装 test自控app失败：", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("安装测试器失败", message));
                                }
                            }
                        });
    }

    /**
     * 安装微信app
     *
     * @param list
     */
    public void installWXApp(final List<DeviceModel> list, final String wxFilePath, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(list)//
                .observeOn(Schedulers.newThread())//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " install " + wxFilePath;

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装wechat app，SQL：", cmd));

                        String result = new ShellExecuter().execCustomShell(cmd, "InstallWechatApp", 77);
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装wechat app反馈：", result));
                        return Observable.just(device);
                    }
                })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<DeviceModel>>() {
                               @Override
                               public void accept(List<DeviceModel> list) {
                                   String s = list.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装wx完毕：", s));
                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.finish("安装wx完毕", LineSeparatorUtil.transformDeviceToListLog("安装微信", list));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String message = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("安装wx失败：", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("安装微信失败", message));
                                }
                            }
                        });
    }

    /**
     * 获取设备id和型号、厂商
     *
     * @param listener
     */
    public void getDeviceSNList(OnGetDeviceSNListListener listener) {
        Observable//
                .create(new ObservableOnSubscribe<DeviceModel>() {
                    @Override
                    public void subscribe(ObservableEmitter<DeviceModel> emitter) throws Exception {
                        List<DeviceModel> list = getDevices();
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("抓设备信息启动线程：", Thread.currentThread().getName()));
                        for (int i = 0; i < list.size(); i++) {
                            emitter.onNext(list.get(i));
                        }
                        emitter.onComplete();
                    }
                })//
                .subscribeOn(Schedulers.newThread())//
                .observeOn(Schedulers.newThread())//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " shell dumpsys power || findstr \"Display Power:state=\"";

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("获取屏幕亮度，SQL：", cmd));

                        String result = new ShellExecuter().execCustomShell(cmd, "GetDisplayState", 33);
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("获取亮屏反馈：", result));
                        if ("OFF".equals(result)) {
                            cmd = "adb -s " + deviceSN + " shell input keyevent 26"; // 唤醒屏幕

                            FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("点亮屏幕，SQL：", cmd));

                            result = new ShellExecuter().execCustomShell(cmd, "GetDisplayState", 33);
                            FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("唤醒屏幕反馈：", result));
                            //cmd = "adb -s " + deviceSN + " shell input keyevent 4";  // 返回
                            //for (int i = 0; i < 8; i++) {
                            //	result = new ShellExecuter().execCustomShell(cmd, "GetDisplayState", 33);
                            //	System.out.println("返回键反馈：" + result);
                            //}
                            //cmd = "adb -s " + deviceSN + " shell input keyevent 3";  // 桌面
                            //result = new ShellExecuter().execCustomShell(cmd, "GetDisplayState", 33);
                            //System.out.println("桌面反馈：" + result);
                        }
                        return Observable.just(device);
                    }
                })//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String deviceSN = device.getSn();
                        String cmd = "adb -s " + deviceSN + " -d shell getprop ro.product.model ; getprop ro.product.brand ; getprop ro.build.version.release ; getprop ro.build.version.sdk ; dumpsys package com.tencent.mm | grep versionName" + System.getProperty("line.separator");

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("获取品牌型号，SQL：", cmd));

                        String info = new ShellExecuter().execCustomShell(cmd, "GetModelAndBrand", 44);
                        String[] split = info.split(System.getProperty("line.separator"));
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("品牌型号返回：", "" + split.length));
                        String model = split[0];   // 型号
                        String brand = split[1];   // 厂商
                        String android = split[2]; // 安卓版本
                        String api = split[3];     // api版本
                        String wx = "null";
                        if (split.length > 4) {
                            wx = split[4];      // 微信版本
                        }
                        device.setModel(model);
                        device.setBrand(brand);
                        device.setAndroidVersion(android);
                        device.setApiVersion(api);
                        device.setWxVersion(wx);
                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("获取型号和厂商反馈：", device.toString()));
                        return Observable.just(device);
                    }
                })//
                .flatMap(new Function<DeviceModel, ObservableSource<DeviceModel>>() {
                    @Override
                    public ObservableSource<DeviceModel> apply(DeviceModel device) throws Exception {
                        String sn = device.getSn();
                        String brand = device.getBrand().toLowerCase().trim();
                        String cmd;
                        String prex;
                        if ("huawei".equals(brand.toLowerCase())) {        // ro.build.version.emui
                            cmd = "adb -s " + sn + " -d shell getprop ro.build.version.emui";
                            prex = "EMUI_";
                        } else if ("xiaomi".equals(brand.toLowerCase())) { // ro.build.version.incremental
                            cmd = "adb -s " + sn + " -d shell getprop ro.build.version.incremental";
                            prex = "MIUI_";
                        } else if ("vivo".equals(brand.toLowerCase())) {   // ro.vivo.os.build.display.id
                            cmd = "adb -s " + sn + " -d shell getprop ro.vivo.os.build.display.id";
                            prex = "Funtouch OS_";
                        } else {
                            cmd = "adb -s " + sn + " -d shell wm size"; // 分辨率
                        }

                        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("获取系统版本，SQL：", cmd));

                        String brandSystemVersion = new ShellExecuter().execCustomShell(cmd, "GetBrandSystemVersion", 49);
                        if ("huawei".equals(brand.toLowerCase())) {
                        } else if ("xiaomi".equals(brand.toLowerCase())) {
                            brandSystemVersion = "MIUI_" + brandSystemVersion; // 只有小米的不带前缀
                        } else if ("vivo".equals(brand.toLowerCase())) {
                        } else {
                            brandSystemVersion = "屏幕分辨率：" + brandSystemVersion;
                        }
                        device.setBrandSystemVersion(brandSystemVersion.toLowerCase().trim());
                        return Observable.just(device);
                    }
                })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<DeviceModel>>() {
                               @Override
                               public void accept(List<DeviceModel> list) {
                                   String s = list.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("设备信息获取完毕：", s));
                                   if (null != listener) {
                                       listener.onGetDeviceSNList(true, list, LineSeparatorUtil.transformDeviceToListLog("获取设备", list));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String s = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("设备信息获取失败：", s));
                                if (null != listener) {
                                    listener.onGetDeviceSNList(false, null, LineSeparatorUtil.transformStrigToListLog("安装微信失败", s));
                                }
                            }
                        });
    }

    /**
     * 查找，添加好友
     *
     * @param deviceList
     * @param friendList
     * @param diffMinTime
     * @param diffMaxTime
     */
    public void testSearching(List<DeviceModel> deviceList, final List<WechatNumberModel> friendList, final int diffMinTime, final int diffMaxTime, final String hello, final String deviceFilePath, final boolean isSameFriends, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(deviceList)//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(//
                         new Function<DeviceModel, ObservableSource<String>>() {
                             @Override
                             public ObservableSource<String> apply(final DeviceModel device) {
                                 String sn = device.getSn();

                                 String deviceSnPath = deviceFilePath;
                                 String path = Constant.sourceWorkSpace + "device_" + sn + ".txt";
                                 if (FileUtil.isExistsFileOrFloder(path)) {
                                     deviceSnPath = path;
                                 }

                                 boolean pushedDevice = PushFileManager.getInstance().isPushedThisFile(device, deviceFilePath);
                                 if (!pushedDevice) { // 避免重复推文件
                                     String cmdPushDevice = "adb -s " + sn + " push " + deviceSnPath + " /sdcard/data/uiautomator20/device.txt"; // 路径须和手机端一致

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("push设备适配文件，SQL：", cmdPushDevice));

                                     String resultPushDevice = new ShellExecuter().execCustomShell(cmdPushDevice, "PushDevice", 57);
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加人推了设备适配文件：", resultPushDevice));
                                 }

                                 List<WechatNumberModel> tmp = new ArrayList<>();
                                 tmp.addAll(friendList);
                                 if (!isSameFriends) { // 没有勾选，即不同手机使用不同的名单
                                     String fp = Constant.sourceWorkSpace + "friend_" + sn.toLowerCase() + ".txt";
                                     File ff = new File(fp);
                                     if (ff.exists()) {
                                         List<WechatNumberModel> wnms = FileUtil.getWechatNumberList(fp);
                                         if (wnms.size() > 0) {
                                             tmp.clear();
                                             tmp.addAll(wnms);
                                             FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("区分好友：设备：", sn + "，" + tmp.toString()));
                                         }
                                     }
                                 }

                                 Observable<String> map = //
                                         Observable//
                                                 .fromIterable(tmp)//
                                                 .observeOn(Schedulers.newThread())// 重新开启新线程
                                                 .map(//
                                                      new Function<WechatNumberModel, String>() {
                                                          @Override
                                                          public String apply(WechatNumberModel arg0) {
                                                              String sn = device.getSn();
                                                              String wxid = arg0.getWxid();
                                                              FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加好友", "手机：" + sn + "，微信：" + wxid));
                                                              String cmd = "adb -s " + sn + " shell am instrument -w -r -e number " + wxid + " -e hello " + hello + " -e debug false -e class 'com.cuiweiyou.uiautomator20.TestSearching#testSearching' com.cuiweiyou.uiautomator20.test/android.support.test.runner.AndroidJUnitRunner";

                                                              FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加好友，SQL：", cmd));

                                                              String result = new ShellExecuter().execCustomShell(cmd, "AddNewFriend=" + wxid, 22);
                                                              FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加好友反馈", result));

                                                              int delay = new Random().nextInt(diffMaxTime - diffMinTime) + diffMinTime;
                                                              return Observable.just(result).delay(delay, TimeUnit.SECONDS).blockingSingle();
                                                              // return result;
                                                          }
                                                      });
                                 return map;
                             }
                         })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<String>>() {
                               @Override
                               public void accept(List<String> modelList) {
                                   String msg = modelList.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加好友完毕", msg));
                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.finish("异步加好友完毕", LineSeparatorUtil.transformStringListToListLog("加好友", modelList));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String message = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("加好友失败", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("加好友失败", message));
                                }
                            }
                        });
    }

    /**
     * 通过陌生好友的主动请求
     */
    public void testAccepting(List<DeviceModel> deviceList, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(deviceList)//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(//
                         new Function<DeviceModel, ObservableSource<String>>() {
                             @Override
                             public ObservableSource<String> apply(final DeviceModel device) throws Exception {
                                 String deviceSN = device.getSn();
                                 String cmd = "adb -s " + deviceSN + " shell am instrument -w -r -e debug false -e class 'com.cuiweiyou.uiautomator20.TestAccepting#testAccepting' com.cuiweiyou.uiautomator20.test/android.support.test.runner.AndroidJUnitRunner";

                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("通过陌生人的主动请求，SQL：", cmd));

                                 String result = new ShellExecuter().execCustomShell(cmd, "AcceptFriend", 51);
                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("陌生好友主动请求通过操作反馈：", result));
                                 return Observable.just(result);
                             }
                         })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<String>>() {
                               @Override
                               public void accept(List<String> modelList) {
                                   String msg = modelList.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("陌生好友主动请求通过完毕：", msg));
                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.finish("陌生好友主动请求通过完毕", LineSeparatorUtil.transformStringListToListLog("通过陌生人请求", modelList));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String message = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("陌生好友主动请求通过失败：", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("通过陌生人请求失败", message));
                                }
                            }
                        });
    }

    /**
     * 遍历聊天
     */
    public void testChatting(List<DeviceModel> deviceList, final String gimmickCommFilePath, final String gimmickHelloFilePath, final String wordFilePath, final String deviceFilePath, final boolean isSameGimmicks, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(deviceList)//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(//
                         new Function<DeviceModel, ObservableSource<String>>() {
                             @Override
                             public ObservableSource<String> apply(final DeviceModel device) {
                                 String deviceSN = device.getSn();

                                 String deviceSnPath = deviceFilePath;
                                 String path = Constant.sourceWorkSpace + "device_" + deviceSN + ".txt";
                                 if (FileUtil.isExistsFileOrFloder(path)) {
                                     deviceSnPath = path;
                                 }

                                 boolean pushedDevice = PushFileManager.getInstance().isPushedThisFile(device, deviceFilePath);
                                 if (!pushedDevice) { // 避免重复推文件
                                     String cmdPushDevice = "adb -s " + deviceSN + " push " + deviceSnPath + " /sdcard/data/uiautomator20/device.txt"; // 路径须和手机端一致

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("聊天推了设备适配文件，SQL：", cmdPushDevice));

                                     String resultPushDevice = new ShellExecuter().execCustomShell(cmdPushDevice, "PushDevice", 56);
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("聊天推了设备适配文件：", resultPushDevice));
                                 }

                                 String commGimmickFile = gimmickCommFilePath;
                                 if (!isSameGimmicks) { // 没有勾选，即不同手机使用不同的话术
                                     String sn_comm = Constant.sourceWorkSpace + "gimmick_comm_" + deviceSN.toLowerCase() + ".txt";
                                     File gimmick_File = new File(sn_comm);
                                     if (gimmick_File.exists() && (gimmick_File.length() > 100)) {
                                         commGimmickFile = sn_comm;
                                     }
                                 }

                                 boolean pushedGimmickComm = PushFileManager.getInstance().isPushedThisFile(device, commGimmickFile);
                                 if (!pushedGimmickComm) { // 避免重复推文件
                                     String cmdPushGimmickComm = "adb -s " + deviceSN + " push " + commGimmickFile + " /sdcard/data/uiautomator20/gimmick_comm.txt"; // 路径须和手机端一致
                                     String resultPushGimmickComm = new ShellExecuter().execCustomShell(cmdPushGimmickComm, "PushCommGimmick", 53);

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("聊天推了comm话术文件：", resultPushGimmickComm));
                                 }

                                 String helloGimmickFile = gimmickHelloFilePath;
                                 if (!isSameGimmicks) {
                                     String sn_hello = Constant.sourceWorkSpace + "gimmick_hello_" + deviceSN.toLowerCase() + ".txt";
                                     File gimmick_File = new File(sn_hello);
                                     if (gimmick_File.exists() && (gimmick_File.length() > 50)) {
                                         helloGimmickFile = sn_hello;
                                     }
                                 }

                                 boolean pushedGimmickHello = PushFileManager.getInstance().isPushedThisFile(device, helloGimmickFile);
                                 if (!pushedGimmickHello) { // 避免重复推文件
                                     String cmdPushGimmickHello = "adb -s " + deviceSN + " push " + helloGimmickFile + " /sdcard/data/uiautomator20/gimmick_hello.txt"; // 路径须和手机端一致
                                     String resultPushGimmickHello = new ShellExecuter().execCustomShell(cmdPushGimmickHello, "PushHelloGimmick", 57);
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("聊天推了hello话术文件：", resultPushGimmickHello));
                                 }

                                 boolean pushedWord = PushFileManager.getInstance().isPushedThisFile(device, wordFilePath);
                                 if (!pushedWord) { // 避免重复推文件
                                     String cmdPushWord = "adb -s " + deviceSN + " push " + wordFilePath + " /sdcard/data/uiautomator20/word.txt"; // 路径须和手机端一致
                                     String resultPushWord = new ShellExecuter().execCustomShell(cmdPushWord, "PushWord", 55);
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("推了话术word文件：", resultPushWord));
                                 }

                                 String cmdChat = "adb -s " + deviceSN + " shell am instrument -w -r -e debug false -e class 'com.cuiweiyou.uiautomator20.TestChatting#testChatting' com.cuiweiyou.uiautomator20.test/android.support.test.runner.AndroidJUnitRunner";

                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("执行聊天，SQL：", cmdChat));

                                 String resultChat = new ShellExecuter().execCustomShell(cmdChat, "TestChatting", 54);
                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("遍历聊天反馈：", resultChat));

                                 return Observable.just(resultChat);
                             }
                         })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<String>>() {
                               @Override
                               public void accept(List<String> modelList) {
                                   String msg = modelList.toString();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("遍历聊天完毕", msg));

                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.finish("遍历聊天完毕", LineSeparatorUtil.transformStringListToListLog("自动聊天", modelList));
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String message = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("遍历聊天失败", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("自动聊天", message));
                                }
                            }
                        });
    }

    /**
     * 提取设备的操作日志db
     *
     * @param outpath    导出到哪。带结尾斜杠 /
     * @param deviceList
     * @param flag       0-db文件，1-txt文件
     */
    public void testPullSqlites(final String outpath, List<DeviceModel> deviceList, final int flag, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(deviceList)//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(//
                         new Function<DeviceModel, ObservableSource<String>>() {
                             @Override
                             public ObservableSource<String> apply(final DeviceModel device) throws Exception {
                                 String deviceSN = device.getSn();
                                 String result;
                                 if (0 == flag) {
                                     String target = outpath + deviceSN + "_" + DateUtil.getNowYYMMDDHHmmss() + ".db";
                                     String cmd = "adb -s " + deviceSN + " pull /sdcard/data/uiautomator20/friend.db " + target;

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull db日志文件，SQL：", cmd));

                                     result = new ShellExecuter().execCustomShell(cmd, "PullSqliteDB", 60);

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull db日志文件反馈", result));
                                 } else {
                                     String target1 = outpath + deviceSN + "_" + DateUtil.getNowYYMMDDHHmmss() + "_fSearch.txt";
                                     String target2 = outpath + deviceSN + "_" + DateUtil.getNowYYMMDDHHmmss() + "_fChat.txt";
                                     String target3 = outpath + deviceSN + "_" + DateUtil.getNowYYMMDDHHmmss() + "_fList.txt";
                                     String cmd1 = "adb -s " + deviceSN + " pull /sdcard/data/uiautomator20/friendSearch.txt " + target1;
                                     String cmd2 = "adb -s " + deviceSN + " pull /sdcard/data/uiautomator20/friendChat.txt " + target2;
                                     String cmd3 = "adb -s " + deviceSN + " pull /sdcard/data/uiautomator20/friendList.txt " + target3;

                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull txt 查找日志文件，SQL：", cmd1));
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull txt 聊天日志文件，SQL：", cmd2));
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull txt 好友日志文件，SQL：", cmd3));

                                     String result1 = new ShellExecuter().execCustomShell(cmd1, "PullFriendSearch", 62);
                                     String result2 = new ShellExecuter().execCustomShell(cmd2, "PullFriendChat", 63);
                                     String result3 = new ShellExecuter().execCustomShell(cmd3, "PullFriendList", 64);

                                     result = result1 + System.getProperty("line.separator") + result2 + System.getProperty("line.separator") + result3;
                                     FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull txt日志文件反馈", result));
                                 }
                                 return Observable.just(result);
                             }
                         })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<String>>() {
                               @Override
                               public void accept(List<String> results) {
                                   String message = results.toString();
                                   List<String> logFile = LineSeparatorUtil.transformStringListToListLog("提取日志", results);
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull日志文件完毕", message));
                                   if (null != onProcessFinishListener) {
                                       if (message.contains("does not exist")) {
                                           onProcessFinishListener.finish("日志文件不存在", logFile);
                                       } else {
                                           onProcessFinishListener.finish(outpath, logFile);
                                       }
                                   }
                               }
                           }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                String message = throwable.getMessage();
                                FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull日志文件失败", message));
                                if (null != onProcessFinishListener) {
                                    onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("提取日志失败", message));
                                }
                            }
                        });
    }

    /**
     * 提取设备的操作日志db
     *
     * @param outpath    导出到哪。带结尾斜杠 /
     * @param deviceList
     */
    public void testPullActions(final String outpath, List<DeviceModel> deviceList, final OnProcessFinishListener onProcessFinishListener) {
        Observable//
                .fromIterable(deviceList)//
                .subscribeOn(Schedulers.newThread())//
                .flatMap(//
                         new Function<DeviceModel, ObservableSource<String>>() {
                             @Override
                             public ObservableSource<String> apply(final DeviceModel device) throws Exception {
                                 String deviceSN = device.getSn();
                                 String cmd = "adb -s " + deviceSN + " pull /sdcard/data/uiautomator20/action_log " + outpath;
                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull action日志文件，SQL：", cmd));

                                 String result = new ShellExecuter().execCustomShell(cmd, "PullActions", 60);
                                 FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull action日志文件反馈", result));

                                 return Observable.just(result);
                             }
                         })//
                .toList()//
                .toObservable()//
                .subscribe(//
                           new Consumer<List<String>>() {
                               @Override
                               public void accept(List<String> results) {
                                   String message = results.toString();
                                   List<String> logFile = LineSeparatorUtil.transformStringListToListLog("提取action日志", results);
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull action日志文件完毕", message));
                                   if (null != onProcessFinishListener) {
                                       if (message.contains("does not exist")) {
                                           onProcessFinishListener.finish("action日志文件不存在", logFile);
                                       } else {
                                           onProcessFinishListener.finish(outpath, logFile);
                                       }
                                   }
                               }
                           }, //
                           new Consumer<Throwable>() {
                               @Override
                               public void accept(Throwable throwable) throws Exception {
                                   String message = throwable.getMessage();
                                   FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("从设备pull action日志文件失败", message));
                                   if (null != onProcessFinishListener) {
                                       onProcessFinishListener.error(LineSeparatorUtil.transformStrigToListLog("提取action日志失败", message));
                                   }
                               }
                           });
    }

    private List<DeviceModel> getDevices() {
        List<DeviceModel> list = new ArrayList<>();
        try {
            String tn = Thread.currentThread().getName();
            FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("当前adb devices任务", tn));
            Process process = Runtime.getRuntime().exec("adb devices");
            InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String sn = null;
            while (null != (sn = br.readLine())) {
                if (sn.contains("device") && !sn.contains("List of")) {
                    sn = sn.replace("device", "");
                    sn = sn.trim();

                    DeviceModel d = new DeviceModel();
                    d.setSn(sn);

                    list.add(d);
                }
            }
            process.waitFor();
            is.close();
            isr.close();
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        FileUtil.saveLogs(LineSeparatorUtil.transformStrigToListLog("adb devices结果", list.toString()));

        return list;
    }

    public static interface OnGetDeviceSNListListener {
        void onGetDeviceSNList(boolean success, List<DeviceModel> list, List<String> logs);
    }

    public static interface OnProcessFinishListener {
        void finish(String note, List<String> logs);

        void error(List<String> logs);
    }

}
